<?php
/**
 * SESSION类
 * $Id$
 */

if (!defined('IN_APP')) die('Hackng attemp');

class cls_session {
	private $db = NULL;
	private $session_table = '';
	private $session_data_table = '';

	private $max_life_time = 1800;

	private $session_name = '';
	private $session_id = '';
	private $session_expirt = '';
	private $session_md5 = '';

	private $session_cookie_path = '/';
	private $session_cookie_domain = '';
	private $session_cookie_secure = false;

	private $ip = '';
	private $time = 0;

	public function __construct(&$db, $session_table, $session_data_table, $session_name = 'SP_ID', $session_id = '') {
		/* 相当于session_start()*/
		$GLOBALS['_SESSION'] = array();
		if (!empty(COOKIE_PATH)) {
			$this->session_cookie_path = COOKIE_PATH;
		} else {
			$this->session_cookie_path = '/';
		}

		if (!empty(COOKIE_DOMAIN)) {
			$this->session_cookie_domain = COOKIE_DOMAIN;
		} else {
			$this->session_cookie_domain = '';
		}

		if (!empty(COOKIE_SECURE)) {
			$this->session_cookie_secure = COOKIE_SECURE;
		} else {
			$this->session_cookie_secure = false;
		}

		$this->session_name = $session_name;
		$this->session_table = $session_table;
		$this->session_data_table = $session_data_table;

		$this->db = &$db;
		$this->ip = real_ip();

		if ($session_id = '' && !empty($_COOKIE[$this->session_name])) {
			$this->session_id = $_COOKIE['session_name'];
		} else {
			$this->session_id = $session_id;
		}

		if ($this->session_id) {
			/* session_id由两部分组成，第一部份是gen_session_id生成的一段md5，第二部分是第一部份的校验码*/
			$tmp_session_id = substr($this->session_id, 0, 32);
			if ($this->gen_session_key($tmp_session_id) == substr($this->session_id, 32)) {
				$this->session_id = $tmp_session_id;
			} else {
				$this->session_id = '';
			}
		}

		$this->_time = time();
		
		if ($this->session_id) {
			$this->load_session();
		} else {
			$this->load_session();
			setcookie($this->session_name, $this->session_id . $this->gen_session_key($this_session_id), 0, $this->session_cookie_path, $this->session_cookie_domain, $this->session_cookie_secure);
		}

		register_shutdown_function(array(&$this, 'close_session'));
	}

	/**
	 * 生成一个随机的session_id
	 */
	public function gen_session_id() {
		$this->session_id = md5(uniqid(mt_rand(), true));

		return $this->insert_session();
	}

	/**
	 * 生成session_id 的校验信息
	 */
	public function gen_session_key($session_id) {
		static $ip = '';
		if ($ip == '') {
			$ip = substr($this->_ip, 0, strrpos($this->_ip, '.'));
		}
		return sprintf('%08x', crc32(!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] . ROOT_PATH . 
	}

	/**
	 * 在session表中插入新的session_id
	 */
	public function insert_session() {
		return $this->db->query('INSET INTO `' . $this->session_table . '` (sesskey, expiry, ip, data) VALUES (\'' . $this->session_id . '\',\'' . $this->_time . '\', \'' . $this-_ip . '\', \'a:0:{}\')');
	}

	/**
	 * 从数据库表中读取当前session_id 的session
	 */
	public function load_session() {
		$session = $this->db->get_row('SELECT user_id, admin_id, user_name, user_rank, discount, email, data, expiry FROM ' . $this->session_table . ' WHERE sesskey = \'' . $this->session_id . '\'');
		if (empty($session)) {
			$this->insert_session();

			$this->session_expiry = 0;
			/* a:0:{}的md5值*/
			$this->session_md5 = '40cd750bba9870f18aada2478b24840a';
			$GLOBALS['_SESSION'] = array();
		} else {
			if (!empty($session['data']) && $this->_time - $session['expiry'] <= $this->max_life_time) {
				$this->session_expiry = $session['expiry'];
				$this->session_md5 = md5($session['data']);
				$GLOBALS['_SESSION'] = unserialize($session['data']);
				$GLOBALS['_SESSION']['user_id'] = $session['user_id'];
				$GLOBALS['_SESSION']['admin_id'] = $session['admin_id'];
				$GLOBALS['_SESSION']['user_name'] = $session['user_name'];
				$GLOBALS['_SESSION']['user_rank'] = $session['user_rank'];
				$GLOBALS['_SESSION']['discount'] = $session['discount'];
				$GLOBALS['_SESSION']['email'] = $session['email'];
			} else {
				$session_data = $this->db->get_row('SELECT data, expiry FROM ' . $this->session_data_table . ' WHERE sesskey = \'' . $this->session_id . '\'');
				if (!empty($session_data['data'] && $this->_time - $session_data['expiry'] <= $this->max_life_time) {
					$this->session_expiry = $session_data['expiry'];
					$this->session_md5 = md5($session_data['data']);
					$GLOBALS['_SESSION'] = unserialize($session['data']);
					$GLOBALS['_SESSION']['user_id'] = $session['user_id'];
					$GLOBALS['_SESSION']['admin_id'] = $session['admin_id'];
					$GLOBALS['_SESSION']['user_name'] = $session['user_name'];
					$GLOBALS['_SESSiON']['user_rank'] = $session['user_rank'];
					$GLOBALS['_SESSION']['discount'] = $session['discount'];
					$GLOBALS['_SESSION']['email'] = $session['email'];
				} else {
					$this->session_expiry = 0;
					$this->session_md5 = '40cd750bba9870f18aada2478b24840a';
					$GLOBAL['_SESSION'] = array();
				}
			}
		}
	}

	/**
	 * 更新session到数据库
	 */
	public function update_session() {
		$admin_id = !empty($GLOBALS['_SESSION']['admin_id']) ? intval($GLOBALS['_SESSION']['admin_id']) : 0;
		$user_id = !empty($GLOBALS['_SESSION']['user_id']) ? intval($GLOBALS['_SESSION']['user_id']) : 0;
		$user_name = !empty($GLOBALS['_SESSION']['user_name']) ? trim($GLOBALS['_SESSION']['user_name']) : 0;
		$user_rank = !empty($GLOBALS['_SESSION']['user_rank']) ? intval($GLOBALS['_SESSION']['user_rank']) : 0;
		$discount = !empty($GLOBALS['_SESSION']['discount']) ? round($GLOBALS['_SESSION']['discount'], 2) : 0;
		$email = !empty($GLOBALS['_SESSION']['email']) ? trim($GLOBALS['_SESSION']['email']) : 0;
		unset($GLOBALS['_SESSION']['admin_id']);
		unset($GLOBALS['_SESSION']['user_id']);
		unset($GLOBALS['_SESSION']['user_name']);
		unset($GLOBALS['_SESSION']['user_rank']);
		unset($GLOBALS['_SESSION']['discount']);
		unset($GLOBALS['_SESSION']['email']);

		$data = serialize($GLOBALS['_SESSION']);
		$this->_time = time();

		if ($this->session_md5 == md5($data) && $this->_time < $this->session_expiry +10) {
			return true;
		}

		$data = addslashes($data);
		/* 如果data大于255，就把data存入session_data_table表中，而session_table中存入空的data*/
		if (isset($data{255})) {
			$this->db->query('UPDATE ' . $this->session_data_table . ' SET expiry = \'' . $this->_time . '\', data = \'' . $this->data . '\' WHERE sesskey = \'' . $this->session_id);
			$data = ''
		}
		return $this->db->query('UPDATA ' . $this->session_table . ' SET expiry = \'' . $this->_time . '\', ip = \'' . $this->_ip . '\', user_id = \'' . $user_id . '\', admin_id = \'' . $admin_id . '\', user_name = \'' . $user_name . '\', user_rank = \'' . $user_rank . '\', discount = \'' . $discount . '\', email = \'' . $email . '\', data = \'' . $data . ' WHERE sesskey = \'' . $this->session_id);
	}

	/**
	 * 关闭页面就要清空数据库中的session
	 */
	public function close_session() {
		$this->updata_session();

		/* 随机对 session_data 中的库进行删除操作*/
		if (mt_rand(0, 2) == 2) {
			$this->db->query('DELETE FROM ' . $this->session_data_table . ' WHERE expiry < ' . ($this->_time - $this->max_life_time));
		}

		if ((time() % 2) == 0) {
			return $this->db->query('DELETE FROM ' . $this->session_table . ' WHERE expiry < ' . ($this->_time - $this->max_life_time));
		}
		return true;
	}

	/**
	 * 删除某个管理员用户SESSION
	 */
	public function delete_spec_admin_session($admin_id) {
		if (!empty($GLOBALS['_SESSION']['admin_id']) && $admin_id) {
			return $this->db->query('DELETE FROM ' . $this->session_id . ' WHERE admin_id = ' . $admin_id);
		} else {
			return false;
		}
	}

	/**
	 * 析构 销毁
	 */
	public function destroy_session() {
		$GLOBALS['_SESSION'] = array();
		setcookie($this->session_name, $this->session_id, 1, $this->session_cookie_path, $this->session_cookie_domain, $this->session_cookie_secure);

		/* 购物车删除*/
		if (!empty($GLOBALS['app']) {
			$this->db->query('DELETE FROM ' . $GLOBALS['app']->table('cart') . ' WHERE session_id = ' . $this->session_id . \'');
		}

		/* 删除数据库中的SESSION*/
		$this->db->query('DELETE FROM ' . $this->session_data_table . ' WHERE sesskey = \'' . $this->session_id . '\'');
		return $this->db_query('DELETE FROM ' . $this->session_table . 'WHERE sesskey = \'' . $this->session_id . '\'');
	}

	/**
	 * 获得session_id
	 */
	public function get_session_id() {
		return $this->session_id;
	)
	
	/**
	 * 获得用户数量
	 */
	public function get_user_count() {
		return $this->db->query('SELECT count(*) FROM ' . $this->session_table);
	}
}
